﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Newtonsoft.Json;

namespace Geek7Utils
{
    class PlayableTool
    {
        public string _projpath = "";
        public string _outpath = "";
        public StringBuilder _buffer = new StringBuilder();
        public string _htmlContent;

        public delegate string ResHandler<in T>(T obj);
        public Dictionary<string, ResHandler<string>> _resHandler = null;

        public PlayableTool(string projpath, string outpath)
        {
            _projpath = projpath;
            _outpath = outpath;

            _resHandler = new Dictionary<string, ResHandler<string>>()
            {
                {".json" , File.ReadAllText},
                {".js", File.ReadAllText},
                {".plist", File.ReadAllText},
                {".pem", File.ReadAllText},
                {".atlas", File.ReadAllText},

                {".wasm", Base64Helper.File2base64},
                {".png", Base64Helper.File2base64},
                {".jpg", Base64Helper.File2base64},
                {".gif", Base64Helper.File2base64},
                {".bin", Base64Helper.File2base64},
                {".mp3", Base64Helper.File2base64},
                {".wav", Base64Helper.File2base64},
                {".mp4", Base64Helper.File2base64},
                {".ttf", Base64Helper.File2base64},
                {".dbbin", Base64Helper.File2base64},
            };
        }


        public void Build()
        {
            //清空Body
            _buffer.Clear();

            //Clean Html;
            string htmlPath = Path.Combine(_projpath, "index.html");
            _htmlContent = File.ReadAllText(htmlPath);

            //剔除link 标签
            _htmlContent = Regex.Replace(_htmlContent, @".*<link(.*)/>.*", "");
            //剔除javaScript
            _htmlContent = Regex.Replace(_htmlContent, @".*<script(.[\s\S]*)</script>.*", "");

            //替换标题
            var regex = Regex.Matches(_htmlContent, @".*<title(.*)title>.*");
            var titile = regex[0].Value.Substring(25, regex[0].Value.Length - 1 - 25 - 8);
            _htmlContent = _htmlContent.Replace(regex[0].Value, $"\t<title>{titile}</title>");

            //嵌入CSS
            string cssContent = File.ReadAllText(Path.Combine(_projpath, "style-mobile.css"));
            //替换Splash
            string splashContent = Base64Helper.Img2base64(Path.Combine(_projpath, "splash.png"));
            cssContent = Regex.Replace(cssContent, @".*background.(.*)no-repeat center;.*", $"background: #171717 url({splashContent}) no-repeat center;");
            _htmlContent = _htmlContent.Replace("</head>", $"\t<style type=\"text/css\">\n{cssContent}\n</style>\n</head >");

            //CCSettings
            string settingjs = "<script charset=\"utf-8\">\n" + File.ReadAllText(Path.Combine(_projpath, "src/settings.js")) + "\n</script>\n";
            _buffer.Append(settingjs);

            //cocos2d-js-min.js
            string ccjs = "<script charset=\"utf-8\">\n" + File.ReadAllText(Path.Combine(_projpath, "cocos2d-js-min.js")) + "\n</script>\n";
            _buffer.Append(ccjs);

            //physics-min.js
            string physicsjspath = Path.Combine(_projpath, "physics-min.js");
            if (File.Exists(physicsjspath))
            {
                string physicsjs = "<script charset=\"utf-8\">\n" + File.ReadAllText(physicsjspath) + "\n</script>\n";
                _buffer.Append(physicsjs);
            }

            //资源嵌入
            var resMap = InlineResources(Path.Combine(_projpath, "assets"), _projpath + "\\");
            string resjs = "<script charset=\"utf-8\">\n" + $"window.resMap={JsonConvert.SerializeObject(resMap)}" + "\n</script>\n";
            _buffer.Append(resjs);

            //嵌入 资源加载重构模块
            string downloaderjs = "<script charset=\"utf-8\">\n" + File.ReadAllText(Path.Combine(Directory.GetCurrentDirectory(), "conf\\downloader-min.js")) + "\n</script>\n";
            _buffer.Append(downloaderjs);

            //main.js
            string mainjs = "<script charset=\"utf-8\">\n" + File.ReadAllText(Path.Combine(_projpath, "main.js")) + "\n</script>\n";
            _buffer.Append(mainjs);

            //window.boot()
            _buffer.Append("<script type=\"text/javascript\">\nwindow.boot();\n</script>\n");

            //嵌入Body内容
            _htmlContent = _htmlContent.Replace("</body>", $"{_buffer.ToString()}\n\n</body>");
        }


        //筛选资源
        private Dictionary<string, string> InlineResources(string dir, string filter = "", Dictionary<string, string> resMap = null)
        {
            if (null == resMap)
                resMap = new Dictionary<string, string>();

            var files = GetFile(dir, new List<FileInfo>());
            try
            {
                foreach (var f in files)
                {
                    string path = f.FullName.Replace(filter, "").Replace("\\", "/");
                    string baseContent = _resHandler[f.Extension](f.FullName);
                    resMap.Add(path, baseContent);
                }
            }
            catch(Exception e)
            {
                Console.WriteLine(e);
            }
            return resMap;
        }

        //输出
        public void OutPut()
        {
            //输出
            File.WriteAllText(_outpath, _htmlContent);
        }


        /// <summary>
        /// 获取路径下所有文件以及子文件夹中文件
        /// </summary>
        /// <param name="path">全路径根目录</param>
        /// <param name="FileList">存放所有文件信息</param>
        /// <returns></returns>
        public List<FileInfo> GetFile(string path, List<FileInfo> FileList)
        {
            DirectoryInfo dir = new DirectoryInfo(path);
            FileInfo[] fil = dir.GetFiles();
            DirectoryInfo[] dii = dir.GetDirectories();
            foreach (FileInfo f in fil)
            {
                //int size = Convert.ToInt32(f.Length);
                //long size = f.Length;
                FileList.Add(f);//添加文件路径到列表中
            }
            //获取子文件夹内的文件列表，递归遍历
            foreach (DirectoryInfo d in dii)
            {
                GetFile(d.FullName, FileList);
            }
            return FileList;
        }

    }
}
